export function stringify(obj){
  return JSON.stringify(obj, (key, value) => {
    if(key.startsWith('$')) return undefined
    if (typeof value === 'function') {
      return value.toString();
    }
    return value === undefined ? null : value;
  });
}

function replaceNull(obj){
  // null, undefined, non-object, function
  if (!obj || typeof obj !== 'object') {
    if(obj === null) return undefined
    return obj
  }
  const result = Array.isArray(obj) ? [] : obj.constructor ? new obj.constructor() : {}
  for (const key in obj) {
    result[key] = replaceNull(obj[key])
  }
  return result
}

export function parse(str) {
  let o = JSON.parse(str,(key, value) => {
    if (typeof value === 'string' && value.startsWith('function')) {
      const functionTemplate = `(${value})`;
      return eval(functionTemplate);
    }
    return value;
  })
  return replaceNull(o)
}
